package com.allwees.bs.c.module.payment.controller;

import com.allwees.bs.c.module.base.controller.BaseController;
import com.allwees.bs.c.module.order.dto.OrderDTO;
import com.allwees.bs.c.module.order.dto.OrderPayDTO;
import com.allwees.bs.c.module.order.entity.OrderEntity;
import com.allwees.bs.c.module.order.service.CartService;
import com.allwees.bs.c.module.payment.req.PaymentCaptureReq;
import com.allwees.bs.c.module.payment.req.PaymentPayByQueryReq;
import com.allwees.bs.c.module.payment.req.PaymentPayPalAppCancelReq;
import com.allwees.bs.c.module.payment.req.PaymentPayPalCheckoutReq;
import com.allwees.bs.c.module.payment.service.impl.PaybyServiceImpl;
import com.allwees.bs.core.modelbase.vo.R;
import com.allwees.core.common.constant.EPlatform;
import com.allwees.core.common.util.http.RequestContext;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

/**
 * payby支付相关
 */
@Slf4j
@RestController
@RequestMapping("/api/v1/payment")
@Api(value = "支付接口", description = "")
public class PaybyPaymentController extends BaseController {

    @Autowired
    private PaybyServiceImpl paybyService;

    @Autowired
    private CartService cartService;

    //*************************************************payby*********************************************************//

    /**
     * 创建payby支付
     *
     * @param req
     * @return
     */
    @PostMapping("/payby/create")
    @ApiOperation("创建支付单")
    public R createPaybyPayment(@ApiParam @RequestBody @Validated PaymentPayPalCheckoutReq req) {
        try {
            return R.ok(paybyService.createPayment(req));
        } catch (Exception e) {
            log.error("payby create order exception", e);
            return R.error("order creation failed");
        }
    }

    /**
     * 取消支付
     *
     * @param req
     * @return
     */
    @PostMapping("/payby/cancel")
    @ApiOperation("取消支付")
    public R cancelPayment(@RequestBody @Validated PaymentPayPalAppCancelReq req) {
        paybyService.cancelPayment(req);
        return R.ok();
    }

    /**
     * 查询支付结果
     *
     * @param req
     * @return
     */
    @PostMapping("/payby/query")
    @ApiOperation("查询支付结果")
    public R queryPayment(@RequestBody @Validated PaymentPayByQueryReq req) {
        log.info("queryPayment req:{}", req);
        OrderPayDTO orderPayDTO = new OrderPayDTO();
        orderPayDTO.setUuid(req.getOrderUuid());
        OrderEntity orderEntity = paybyService.queryOrderStatus(req.getOrderUuid());
        if (orderEntity.getPayed()) {
            orderPayDTO.setStatus("PAYED");
        } else {
            Map<String, String> payResult = paybyService.queryPaymentFromPayby(req.getOrderUuid());
            log.warn("order id:{}, queryPayment result:{}", req.getOrderUuid(), payResult);
            String status = payResult.get("status");

            if (StringUtils.equals("PAYED", status)) {
                PaymentCaptureReq paymentCaptureReq = new PaymentCaptureReq();
                paymentCaptureReq.setOrderUuid(req.getOrderUuid());
//                paymentCaptureReq.setToken(null);
                paymentCaptureReq.setPayerId(getUserUuid());
//                MqUtil.send(new PaypalCaptureEvent(paymentCaptureReq));
                cartService.clearUserCart(getUserUuid());
                paybyService.orderPayed(paymentCaptureReq);
            } else if (StringUtils.equals("FAILURE", status)) {
                log.warn("OrderPay failed, order id:{}", req.getOrderUuid());
            } else {
                log.warn("OrderPay unknown status, order id:{}", req.getOrderUuid());
            }
            orderPayDTO.setStatus(status);
            orderPayDTO.setMsg(payResult.get("msg"));
        }

        return R.ok(orderPayDTO);
    }

    /**
     * payby支付捕获
     *
     * @param req
     * @return
     */
    @PostMapping("/app/payby/capture")
    @ApiOperation("目前没用")
    public R createAppPayment(@RequestBody @Validated PaymentCaptureReq req) {
        OrderDTO dto = paybyService.appCapture(req);
        return R.ok(dto);
    }

    /**
     * payby支付捕获
     *
     * @param req
     * @return
     */
    @PostMapping("/payby/capture")
    @ApiOperation("目前没用")
    public R paybyCapture(@RequestBody PaymentCaptureReq req) {
        //mq
//        MqUtil.send(new PaypalCaptureEvent(req));

        cartService.clearUserCart(getUserUuid());
        OrderDTO order = this.paybyService.orderPayed(req);

        return R.ok(order);
    }

    /**
     * payby回调 支付成功，暂时没用
     *
     * @return
     */
    @GetMapping("/app/payby/return")
    public ModelAndView paybyAppReturn(@RequestParam(value = "token") String paymentId,
                                       @RequestParam(value = "PayerID") String payerId,
                                       @RequestParam(value = "orderUuid") String orderUuid,
                                       @RequestParam(value = "platform") String platform) {
        log.info("paybyAppReturn >>>>>>>>>>>>>>>>>>>>>>>>>>>> paymentId:{},payerId:{},orderUuid:{},platform:{}", paymentId, payerId, orderUuid, platform);

        PaymentCaptureReq captureReq = new PaymentCaptureReq(paymentId, payerId, orderUuid, EPlatform.parseFrom(platform), RequestContext.getChannel());
        OrderDTO order = this.paybyService.orderPayed(captureReq);
        return _appView(captureReq.getPlatform(), "succeed", orderUuid);
    }

    /**
     * payby回调 取消支付
     *
     * @param orderUuid
     * @param platform
     * @return
     */
    @GetMapping("/app/payby/cancel")
    @ApiOperation("取消支付,直接跳转页面")
    public ModelAndView paybyCancel(@RequestParam(value = "orderUuid") String orderUuid,
                                    @RequestParam(value = "platform") String platform) {
        log.info("paybyCancel >>>>>>>>>>>>>>>>>>>>>>>>>>>> orderUuid:{},platform:{}", orderUuid, platform);
        return _appView(EPlatform.parseFrom(platform), "cancelled", orderUuid);
    }

    private ModelAndView _appView(EPlatform platform, String templateNameSuffix, String orderUuid) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("orderUuid", orderUuid);
        mv.setViewName(_getAppWebViewTemplate(platform, templateNameSuffix));
        return mv;
    }

    private String _getAppWebViewTemplate(EPlatform platform, String templateNameSuffix) {
        return platform.name().toLowerCase() + "_payment_" + templateNameSuffix;
    }
}
